package osmconf

import (
	"bytes"
	"crypto/ecdsa"
	"crypto/sha256"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/wanchain/go-mpc/accounts"
	"github.com/wanchain/go-mpc/accounts/keystore"
	"github.com/wanchain/go-mpc/common"
	"github.com/wanchain/go-mpc/common/hexutil"
	"github.com/wanchain/go-mpc/crypto"
	"github.com/wanchain/go-mpc/log"
	"github.com/wanchain/go-mpc/p2p/discover"
	schcomm "github.com/wanchain/go-mpc/storeman/schnorrcomm"
	mpcprotocol "github.com/wanchain/go-mpc/storeman/storemanmpc/protocol"
	"io/ioutil"
	"math/big"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"
)

const EmptyString = ""

var osmConf *OsmConf

type GrpElem struct {
	Inx       uint16
	WorkingPk *ecdsa.PublicKey
	NodeId    *discover.NodeID
	XValue    *big.Int
	Address   string
}
type PkShare struct {
	Inx          uint16
	PkShareBytes hexutil.Bytes
}

type GrpCurve struct {
	Gpk       hexutil.Bytes
	CurveType string
	PkShares  ArrayPkShare
}

type ArrayGrpElem []GrpElem
type ArrayGrpCurve []GrpCurve
type ArrayPkShare []PkShare
type ArrayNodeElem []discover.NodeID

func (x ArrayNodeElem) Len() int { return len(x) }
func (x ArrayNodeElem) Less(i, j int) bool {
	if bytes.Compare(x[i][:], x[j][:]) < 0 {
		return true
	}
	return false
}
func (x ArrayNodeElem) Swap(i, j int) { x[i], x[j] = x[j], x[i] }

type ArrayGrpElemsInx []uint16

type GrpInfoItem struct {
	GrpId        string
	LeaderInx    uint16
	TotalNum     uint16
	ThresholdNum uint16
	ArrGrpElems  ArrayGrpElem
	ArrGrpCurves ArrayGrpCurve
}

type MapIndxToNodeId map[uint16]*discover.NodeID
type MapNodeIdToIndx map[string]uint16

type OsmConf struct {
	GrpInfoMap      map[string]GrpInfoItem
	SelfNodeId      *discover.NodeID
	GpkPassword     string
	WorkingPassword string
	AccMng          *accounts.Manager
	confPath        string
	pwdPath         string
	wrLock          sync.RWMutex
	wrLockPrv       sync.RWMutex
	pwdFileMap      map[string]string
	password        string
	selfPrvKey      *ecdsa.PrivateKey
	kmsInfo         *KmsInfo
	bootNodeID      *discover.NodeID
	sortedAllNodes  ArrayNodeElem
	//mapAllGrpElems  map[discover.NodeID]uint8
	mapAllGrpElems    map[string]uint8
	GrpIdIndxToNodeId map[string]MapIndxToNodeId
	GrpIdNodeIdToIndx map[string]MapNodeIdToIndx
}

//-----------------------configure content begin ---------------------------------
type PkShareContent struct {
	Inx     string        `json:"index"`
	PkShare hexutil.Bytes `json:"pkShare"`
}

type GrpElemContent struct {
	Inx       string        `json:"index"`
	WorkingPk hexutil.Bytes `json:"workingPk"`
	NodeId    hexutil.Bytes `json:"nodeId"`
	Address   string        `json:"address"`
}

type GrpCurveContent struct {
	Gpk       hexutil.Bytes    `json:"gpk"`
	CurveType string           `json:"curveType"`
	PkShares  []PkShareContent `json:"pkShares"`
}

type GrpInfoItemContent struct {
	GrpId           string            `json:"grpId"`
	LeaderInx       string            `json:"leaderInx"`
	TotalNumber     string            `json:"totalNumber"`
	ThresholdNumber string            `json:"thresholdNumber"`
	GrpElms         []GrpElemContent  `json:"grpElms"`
	GrpCurves       []GrpCurveContent `json:"grpCurves"`
}

type OsmFileContent struct {
	GrpInfo []GrpInfoItemContent
}

//-----------------------configure content end ---------------------------------

func GetOsmConf() *OsmConf {

	if osmConf == nil {
		osmConf = new(OsmConf)
		discover.SetHLNode(osmConf)
		return osmConf
	}
	return osmConf
}

//-----------------------mange config file ---------------------------------

func (cnf *OsmConf) LoadCnf(confPath string) error {

	defer cnf.wrLock.Unlock()

	var err error
	if confPath == EmptyString {
		err = errors.New("confPath is empty")
		log.SyslogErr(err.Error())
		return err
	}
	ofcContent := OsmFileContent{}

	filePath := confPath

	cnf.wrLock.Lock()
	// clear group info
	cnf.GrpInfoMap = make(map[string]GrpInfoItem)
	cnf.mapAllGrpElems = make(map[string]uint8)
	cnf.sortedAllNodes = make(ArrayNodeElem, 0)

	cnf.GrpIdIndxToNodeId = make(map[string]MapIndxToNodeId)
	cnf.GrpIdNodeIdToIndx = make(map[string]MapNodeIdToIndx)

	b, err := ioutil.ReadFile(filePath)
	if err != nil {
		log.SyslogErr("LoadCnf.ReadFile", "error", err.Error())
		return err
	}
	errUnmarshal := json.Unmarshal(b, &ofcContent)
	if errUnmarshal != nil {
		log.SyslogErr("LoadCnf.Unmarshal", "error", errUnmarshal.Error())
		return errUnmarshal
	}

	// save configure file content to the OsmConf struct.

	cnf.GrpInfoMap = make(map[string]GrpInfoItem, len(ofcContent.GrpInfo))
	for _, grpInfo := range ofcContent.GrpInfo {

		if _, exist := cnf.GrpIdNodeIdToIndx[grpInfo.GrpId]; !exist {
			cnf.GrpIdNodeIdToIndx[grpInfo.GrpId] = make(MapNodeIdToIndx)
		}
		if _, exist := cnf.GrpIdIndxToNodeId[grpInfo.GrpId]; !exist {
			cnf.GrpIdIndxToNodeId[grpInfo.GrpId] = make(MapIndxToNodeId)
		}

		gii := GrpInfoItem{}

		gii.GrpId = grpInfo.GrpId

		leaderIndex, _ := strconv.Atoi(grpInfo.LeaderInx)
		gii.LeaderInx = uint16(leaderIndex)

		TotalNum, _ := strconv.Atoi(grpInfo.TotalNumber)
		gii.TotalNum = uint16(TotalNum)

		ThresholdNum, _ := strconv.Atoi(grpInfo.ThresholdNumber)
		gii.ThresholdNum = uint16(ThresholdNum)

		gii.ArrGrpElems = make(ArrayGrpElem, len(grpInfo.GrpElms))

		for i, ge := range grpInfo.GrpElms {

			Inx, _ := strconv.Atoi(ge.Inx)
			gii.ArrGrpElems[i].Inx = uint16(Inx)

			var wpkBytes []byte
			if len(ge.WorkingPk) == 64 {
				wpkBytes = schcomm.Add04Prefix(ge.WorkingPk)
			} else {
				if len(ge.WorkingPk) == 65 {
					wpkBytes = ge.WorkingPk
				}
			}

			gii.ArrGrpElems[i].WorkingPk = crypto.ToECDSAPub(wpkBytes)
			//gii.ArrGrpElems[i].WorkingPk = crypto.ToECDSAPub(ge.WorkingPk)

			nodeId := discover.NodeID{}
			copy(nodeId[:], ge.NodeId[:])
			gii.ArrGrpElems[i].NodeId = &nodeId

			h := sha256.Sum256(ge.WorkingPk)
			gii.ArrGrpElems[i].XValue = big.NewInt(0).SetBytes(h[:])
			gii.ArrGrpElems[i].Address = ge.Address
			if _, exist := cnf.mapAllGrpElems[nodeId.String()]; !exist {
				cnf.mapAllGrpElems[nodeId.String()] = 0
			}

			if _, exist := cnf.GrpIdNodeIdToIndx[grpInfo.GrpId][nodeId.String()]; !exist {
				cnf.GrpIdNodeIdToIndx[grpInfo.GrpId][nodeId.String()] = uint16(Inx)
			}

			nodeIdTemp := discover.NodeID{}
			copy(nodeIdTemp[:], ge.NodeId[:])
			if _, exist := cnf.GrpIdIndxToNodeId[grpInfo.GrpId][uint16(Inx)]; !exist {
				cnf.GrpIdIndxToNodeId[grpInfo.GrpId][uint16(Inx)] = &nodeIdTemp
			}
		}

		gii.ArrGrpCurves = make(ArrayGrpCurve, len(grpInfo.GrpCurves))

		for i, gc := range grpInfo.GrpCurves {

			gcTemp := GrpCurve{}
			gcTemp.Gpk = gc.Gpk
			gcTemp.CurveType = gc.CurveType
			gcTemp.PkShares = make(ArrayPkShare, len(gc.PkShares))

			for j, pkShare := range gc.PkShares {
				inx, _ := strconv.Atoi(pkShare.Inx)
				gcTemp.PkShares[j].Inx = uint16(inx)
				gcTemp.PkShares[j].PkShareBytes = pkShare.PkShare
			}
			gii.ArrGrpCurves[i] = gcTemp
		}
		if _, exist := cnf.GrpInfoMap[grpInfo.GrpId]; !exist {
			cnf.GrpInfoMap[grpInfo.GrpId] = gii
		}
	}

	for nodeIdstr, _ := range cnf.mapAllGrpElems {
		nodeId, _ := discover.HexID(nodeIdstr)
		cnf.sortedAllNodes = append(cnf.sortedAllNodes, nodeId)
	}
	sort.Sort(cnf.sortedAllNodes)

	for flatIndex, nodeId := range cnf.sortedAllNodes {
		log.SyslogInfo("LoadCnf", "flatIndex", flatIndex, "nodeId", nodeId.SlimString())
		cnf.mapAllGrpElems[nodeId.String()] = uint8(flatIndex)
	}
	return nil
}

func (cnf *OsmConf) IndexByNodeId_org(nodeId discover.NodeID) uint8 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	return cnf.mapAllGrpElems[nodeId.String()]
}

func (cnf *OsmConf) IndexByNodeId(grpId string, nodeId discover.NodeID) uint8 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	ret, _ := cnf.GetInxByNodeId(grpId, &nodeId)
	return uint8(ret)
}

func (cnf *OsmConf) NodeIdByIndex_org(index uint8) discover.NodeID {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret discover.NodeID
	if int(index) < len(cnf.sortedAllNodes) {
		copy(ret[:], (cnf.sortedAllNodes[int(index)])[:])
		return ret
	}
	return *(mpcprotocol.GetNilNodeId())
}

func (cnf *OsmConf) NodeIdByIndex(grpId string, index uint8) discover.NodeID {

	nodeId, err := cnf.GetNodeIdByIndex(grpId, uint16(index))
	if err != nil {
		return *(mpcprotocol.GetNilNodeId())
	}
	return *nodeId
}

func (cnf *OsmConf) NodeIdsByUint_org(peers uint64) []*discover.NodeID {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret []*discover.NodeID
	for i := 0; i < int(cnf.NodeLen_org()); i++ {
		if peers&(1<<uint8(i)) != 0 {
			var nodeId discover.NodeID
			copy(nodeId[:], cnf.sortedAllNodes[int(i)][:])
			ret = append(ret, &nodeId)
		}
	}
	return ret
}

func (cnf *OsmConf) NodeIdsByUint(grpId string, peers uint64) []*discover.NodeID {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret []*discover.NodeID

	if grpInfo, exist := cnf.GrpInfoMap[grpId]; exist {
		for i := 0; i < int(cnf.NodeLen(grpId)); i++ {
			if peers&(1<<uint8(i)) != 0 {
				var nodeId discover.NodeID
				copy(nodeId[:], grpInfo.ArrGrpElems[int(i)].NodeId[:])
				ret = append(ret, &nodeId)
			}
		}
	}
	return ret
}

func (cnf *OsmConf) NodeLen_org() uint8 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	return uint8(len(cnf.sortedAllNodes))
}

func (cnf *OsmConf) NodeLen(grpId string) uint8 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	if grpInfo, exist := cnf.GrpInfoMap[grpId]; exist {
		return uint8(len(grpInfo.ArrGrpElems))
	}
	return uint8(0)
}

func (cnf *OsmConf) BuildAllNodesBits_org() uint64 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret uint64
	for i, _ := range cnf.sortedAllNodes {
		ret = ret | 1<<uint8(i)
	}
	return ret
}

func (cnf *OsmConf) BuildAllNodesBits(grpId string) uint64 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret uint64
	if grpInfo, exist := cnf.GrpInfoMap[grpId]; exist {
		for i, _ := range grpInfo.ArrGrpElems {
			ret = ret | 1<<uint8(i)
		}
	}
	return ret
}

func (cnf *OsmConf) BuildNodesBitsByNodes_org(nodeIds []*discover.NodeID) uint64 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret uint64
	for _, nodeId := range nodeIds {
		if value, exist := cnf.mapAllGrpElems[nodeId.String()]; exist {
			ret = ret | 1<<value
		}
	}
	return ret
}

func (cnf *OsmConf) BuildNodesBitsByNodes(grpId string, nodeIds []*discover.NodeID) uint64 {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()
	var ret uint64
	for _, nodeId := range nodeIds {
		value, _ := cnf.GetInxByNodeId(grpId, nodeId)
		ret = ret | 1<<value
	}
	return ret
}

func (cnf *OsmConf) FreshCnf(confPath string) error {
	if confPath == EmptyString {
		log.SyslogErr("FreshCnf confPath is empty")
		return errors.New("FreshCnf confPath is empty")
	}
	err := cnf.LoadCnf(confPath)
	if err != nil {
		return err
	}
	cnf.SetSelfWorkingAddr()
	return nil
}

func (cnf *OsmConf) checkGrpId(grpId string) bool {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	if _, ok := cnf.GrpInfoMap[grpId]; !ok {

		errStr := fmt.Sprintf("checkGrpId: groupId does not exist in storeman group. grpId %v", grpId)
		log.SyslogErr("checkGrpId", "err", errStr)
		return false
	} else {
		return true
	}
}

func (cnf *OsmConf) GetThresholdNum(grpId string) (uint16, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)

	return cnf.GrpInfoMap[grpId].ThresholdNum, nil

}

func (cnf *OsmConf) GetThresholdNumByCurve(grpId string, curveType uint8) (uint16, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	if int(curveType) == mpcprotocol.SK256Curve {
		// Btc and xrp using sk256 curve, and sec curve is used for btc signature
		return cnf.GrpInfoMap[grpId].ThresholdNum / 2, nil
	}
	return cnf.GrpInfoMap[grpId].ThresholdNum, nil
}

func (cnf *OsmConf) GetTotalNum(grpId string) (uint16, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)

	return cnf.GrpInfoMap[grpId].TotalNum, nil
}

// get working pk
func (cnf *OsmConf) GetPK(grpId string, smInx uint16) (*ecdsa.PublicKey, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)

	arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	for _, value := range arrGrpElem {
		if value.Inx == smInx {
			return value.WorkingPk, nil
		}
	}
	errStr := fmt.Sprintf("GetPK:Not find storeman, smInx %v", smInx)
	log.SyslogErr("OsmConf.GetPK", "err", errStr)
	return nil, errors.New(errStr)
}

func (cnf *OsmConf) GetPKByNodeId(grpId string, nodeId *discover.NodeID) (*ecdsa.PublicKey, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	if nodeId == nil {
		errStr := fmt.Sprintf("GetPKByNodeId, nodeId is null")
		log.SyslogErr("OsmConf.GetPKByNodeId", "err", errStr)
		return nil, errors.New(errStr)
	}
	arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	for _, value := range arrGrpElem {
		if *value.NodeId == *nodeId {
			return value.WorkingPk, nil
		}
	}

	errStr := fmt.Sprintf("GetPKByNodeId:Not find storeman, nodeId %v", *nodeId)
	log.SyslogErr("OsmConf.GetPKByNodeId", "err", errStr)
	return nil, errors.New(errStr)
}

func (cnf *OsmConf) GetFirstPKByNodeId(nodeId *discover.NodeID) (*ecdsa.PublicKey, error) {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	if nodeId == nil {
		errStr := fmt.Sprintf("GetPKByNodeId, nodeId is null")
		log.SyslogErr("OsmConf.GetPKByNodeId", "err", errStr)
		return nil, errors.New(errStr)
	}

	for _, GrpInfoItem := range cnf.GrpInfoMap {
		for _, value := range GrpInfoItem.ArrGrpElems {
			if *value.NodeId == *nodeId {
				return value.WorkingPk, nil
			}
		}
	}

	errStr := fmt.Sprintf("GetPKByNodeId:Not find storeman, nodeId %v", *nodeId)
	log.SyslogErr("OsmConf.GetPKByNodeId", "err", errStr)
	return nil, errors.New(errStr)
}

// get gpk share (public share)
func (cnf *OsmConf) GetPKShareBytes(grpId, gpk string, smInx uint16, curveType uint16) ([]byte, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	arrGrpCurve := cnf.GrpInfoMap[grpId].ArrGrpCurves
	for _, value := range arrGrpCurve {
		gpkStr := hexutil.Encode(value.Gpk)
		if strings.Compare(value.CurveType, strconv.Itoa(int(curveType))) == 0 && strings.Compare(gpkStr, gpk) == 0 {
			for _, ps := range value.PkShares {
				if ps.Inx == smInx {
					return ps.PkShareBytes, nil
				}
			}
		}
	}

	errStr := fmt.Sprintf("GetPKShare:Not find storeman, smInx %v", smInx)
	log.SyslogErr("OsmConf.GetPKShareBytes", "err", errStr)
	return nil, errors.New(errStr)
}

//-----------------------get self---------------------------------

func (cnf *OsmConf) getSelfPubKey() (*ecdsa.PublicKey, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	for _, grpInfo := range cnf.GrpInfoMap {
		for _, grpElem := range grpInfo.ArrGrpElems {
			if *grpElem.NodeId == *cnf.SelfNodeId {
				return grpElem.WorkingPk, nil
			}
		}
	}
	errStr := fmt.Sprintf("GetSelfPubKey:Not find storeman, selfNodeId %v", *cnf.SelfNodeId)
	log.SyslogErr("OsmConf.getSelfPubKey", "err", errStr)
	return nil, errors.New(errStr)
}

func (cnf *OsmConf) GetSelfInx(grpId string) (uint16, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	return cnf.GetInxByNodeId(grpId, cnf.SelfNodeId)
}

func (cnf *OsmConf) GetSelfNodeId() (*discover.NodeID, error) {
	//defer cnf.wrLock.RUnlock()
	//
	//cnf.wrLock.RLock()

	return cnf.SelfNodeId, nil
}

func (cnf *OsmConf) GetSelfPrvKey() (*ecdsa.PrivateKey, error) {

	cnf.wrLockPrv.RLock()
	if cnf.selfPrvKey != nil {
		cnf.wrLockPrv.RUnlock()
		return cnf.selfPrvKey, nil
	}
	cnf.wrLockPrv.RUnlock()

	pk, err := cnf.getSelfPubKey()
	if err != nil {
		log.SyslogErr("OsmConf", "GetSelfPrvKey.GetSelfPubKey", err.Error())
		return nil, err
	}
	if pk == nil {
		log.SyslogErr("OsmConf GetSelfPrvKey pk == nil")
		return nil, err
	}
	err = schcomm.CheckPK(pk)
	if err != nil {
		log.SyslogErr("OsmConf", "GetSelfPrvKey.CheckPK", err.Error())
		return nil, err
	}
	address, err := pkToAddr(crypto.FromECDSAPub(pk))
	log.SyslogInfo("GetSelfPrvKey", "pk", hexutil.Encode(crypto.FromECDSAPub(pk)), "address", address.String())
	if err != nil {

		errStr := fmt.Sprintf("Error in pk to address")
		log.SyslogErr("OsmConf.GetSelfPrvKey", "err", errStr)
		return nil, errors.New(errStr)

	}

	ks := cnf.AccMng.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
	account := accounts.Account{Address: address}
	account, err = ks.Find(account)
	if err != nil {
		//find account from keystore fail

		errStr := fmt.Sprintf("find account from keystore fail")
		log.SyslogErr("OsmConf.GetSelfPrvKey", "err", errStr)
		return nil, errors.New(errStr)

	}

	var keyjson []byte
	log.Info("GetSelfPrvKey", "account.URL.Path", account.URL.Path)
	keyjson, err = ioutil.ReadFile(account.URL.Path)

	if err != nil {
		// get account keyjson fail
		errStr := fmt.Sprintf("ReadFile keystore file fail")
		log.SyslogErr("OsmConf.GetSelfPrvKey", "err", errStr)
		return nil, errors.New(errStr)
	}

	wkPassword, _ := cnf.GetWkPwd(address.String())
	key, err := keystore.DecryptKey(keyjson, wkPassword)
	if err != nil {
		// decrypt account keyjson fail
		errStr := fmt.Sprintf("DecryptKey keystore file fail error %s", err.Error())
		log.SyslogErr("OsmConf.GetSelfPrvKey", "err", errStr)
		return nil, errors.New(errStr)

	}

	cnf.wrLockPrv.Lock()
	cnf.selfPrvKey = key.PrivateKey
	cnf.wrLockPrv.Unlock()

	return key.PrivateKey, nil
}

func (cnf *OsmConf) SetSelfNodeId(id *discover.NodeID) error {
	defer cnf.wrLock.Unlock()
	cnf.wrLock.Lock()

	if id == nil {
		errStr := fmt.Sprintf("SetSelfNodeId, nodeId is null")
		log.SyslogErr("OsmConf.SetSelfNodeId", "err", errStr)
		return errors.New(errStr)
	}
	log.SyslogInfo(fmt.Sprintf(">>>>>>>SetSelfNodeId %v \n", id.String()))
	cnf.SelfNodeId = id

	log.SetSelfNodeId(id.SlimString())

	return nil
}

func (cnf *OsmConf) SetSelfWorkingAddr() error {
	log.SetSelfWorkAddr(cnf.GetSelfWorkAddr())
	return nil
}

func (cnf *OsmConf) SetAccountManger(accMng *accounts.Manager) error {

	if accMng == nil {
		errStr := fmt.Sprintf("SetAccountManger accMng is null")
		log.SyslogErr("OsmConf.SetAccountManger", "err", errStr)
		return errors.New(errStr)
	}
	cnf.AccMng = accMng
	return nil
}

func (cnf *OsmConf) SetFilePath(path string) error {
	if path == EmptyString {
		errStr := fmt.Sprintf("SetFilePath path is empty")
		log.SyslogErr("OsmConf.SetFilePath", "err", errStr)
		return errors.New(errStr)
	}
	cnf.confPath = path
	return nil
}

func (cnf *OsmConf) GrpInfoPath() string {
	return cnf.confPath
}

func (cnf *OsmConf) GetGpkPwd(gpk string) (string, error) {

	//fn, _ := cnf.getPwdFileName(gpk + ".pwd")
	//fileName := path.Join(cnf.pwdPath, fn)
	//// get password from file
	//return cnf.GetPwd(fileName)
	return cnf.password, nil
}

func (cnf *OsmConf) GetWkPwd(address string) (string, error) {
	//fn, _ := cnf.getPwdFileName(address + ".pwd")
	//fileName := path.Join(cnf.pwdPath, fn)
	//return cnf.GetPwd(fileName)
	return cnf.password, nil
}

func (cnf *OsmConf) GetPwd(fileName string) (string, error) {
	//if fileName == "" {
	//
	//	errStr := fmt.Sprintf("password file [:%v] is not existing", fileName)
	//	log.SyslogErr("OsmConf.GetPwd", "err", errStr)
	//	return "", errors.New(errStr)
	//
	//}
	//text, err := ioutil.ReadFile(fileName)
	//if err != nil {
	//	errStr := fmt.Sprintf("Failed to read password file:[%v]", fileName)
	//	log.SyslogErr("OsmConf.GetPwd", "err", errStr)
	//	return "", errors.New(errStr)
	//
	//}
	//lines := strings.Split(string(text), "\n")
	//if len(lines) == 0 {
	//	errStr := fmt.Sprintf("empty password [%v]", fileName)
	//	log.SyslogErr("OsmConf.GetPwd", "err", errStr)
	//	return "", errors.New(errStr)
	//
	//}
	//// Sanitise DOS line endings.
	//for i := range lines {
	//	lines[i] = strings.TrimRight(lines[i], "\r")
	//}
	//return lines[0], nil
	return cnf.password, nil
}

func (cnf *OsmConf) SetPwd(password string) {
	cnf.password = password
}

func (cnf *OsmConf) SetKmsInfo(info *KmsInfo) {
	cnf.kmsInfo = info
}

func (cnf *OsmConf) KmsInfo() (info *KmsInfo) {
	return cnf.kmsInfo
}

//func (cnf *OsmConf) SetPwdPath(path string) error {
//	if path == EmptyString {
//
//		errStr := fmt.Sprintf("SetFilePath path is empty")
//		log.SyslogErr("OsmConf.SetPwdPath", "err", errStr)
//		return errors.New(errStr)
//	}
//	cnf.pwdPath = path
//	cnf.buildPwdMap(path)
//	return nil
//}

//func (cnf *OsmConf) buildPwdMap(dir string) error {
//	cnf.pwdFileMap = make(map[string]string, 0)
//	flist, err := ioutil.ReadDir(dir)
//
//	if err != nil {
//		return err
//	}
//
//	for _, f := range flist {
//		key := strings.ToUpper(f.Name())
//		cnf.pwdFileMap[key] = f.Name()
//	}
//	return nil
//}

//func (cnf *OsmConf) getPwdFileName(incaseFielName string) (string, error) {
//	ret, ok := cnf.pwdFileMap[strings.ToUpper(incaseFielName)]
//	if ok {
//		return ret, nil
//	}
//	return incaseFielName, nil
//}

//-----------------------get group---------------------------------

func (cnf *OsmConf) GetGrpElemsInxes(grpId string) (*ArrayGrpElemsInx, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)
	ret := make(ArrayGrpElemsInx, len(cnf.GrpInfoMap[grpId].ArrGrpElems))
	arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	for index, value := range arrGrpElem {
		ret[index] = value.Inx
	}
	return &ret, nil
}

func (cnf *OsmConf) getGrpElems(grpId string) (*ArrayGrpElem, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)
	ArrayGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	return &ArrayGrpElem, nil

}

func (cnf *OsmConf) getGrpItem(grpId string, smInx uint16) (*GrpElem, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)
	arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems

	for index, grpElem := range arrGrpElem {
		if uint16(index) == smInx {
			return &grpElem, nil
		}
	}

	errStr := fmt.Sprintf("getGrpItem error. grpId = %v,smInx=%v", grpId, smInx)
	log.SyslogErr("OsmConf.getGrpItem", "err", errStr)
	return nil, errors.New(errStr)

}

func (cnf *OsmConf) GetGrpItem(grpId string, smInx uint16) (*GrpElem, error) {
	return cnf.getGrpItem(grpId, smInx)
}

func (cnf *OsmConf) GetGrpInxByGpk(gpk hexutil.Bytes) (string, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	for index, value := range cnf.GrpInfoMap {
		for _, gc := range value.ArrGrpCurves {
			if bytes.Compare(gc.Gpk, gpk) == 0 {
				return index, nil
			}
		}
	}

	errStr := fmt.Sprintf("GetGrpInxByGpk error. gpk = %v ", hexutil.Encode(gpk))
	log.SyslogErr("OsmConf.GetGrpInxByGpk", "err", errStr)
	return EmptyString, errors.New(errStr)
}

func (cnf *OsmConf) IsInGroup(pk *ecdsa.PublicKey) bool {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	for _, value := range cnf.GrpInfoMap {
		for _, elem := range value.ArrGrpElems {
			if elem.WorkingPk.Equal(pk) {
				return true
			}
		}
	}
	return false
}

func (cnf *OsmConf) IsSelfInGroup(grpId string) bool {
	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	if value, exist := cnf.GrpInfoMap[grpId]; exist {
		for _, elem := range value.ArrGrpElems {
			if bytes.Equal((*elem.NodeId)[:], (*cnf.SelfNodeId)[:]) {
				return true
			}
		}
	}
	return false
}

func (cnf *OsmConf) BuildLosingByIndex(grpId string, losingIndexs []uint16) string {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	var ret string
	mapIndex := make(map[uint16]bool)
	for _, index := range losingIndexs {
		mapIndex[index] = true
	}
	for index, grpElem := range arrGrpElem {
		_, ok := mapIndex[uint16(index)]
		if ok {
			ret += grpElem.Address + ","
		}

	}
	return ret
}

func (cnf *OsmConf) GetWorkingAddrByNodeId(nodeId *discover.NodeID) string {
	defer cnf.wrLock.RUnlock()
	var ret string
	cnf.wrLock.RLock()
	for _, value := range cnf.GrpInfoMap {
		arrGrpElem := value.ArrGrpElems
		for _, grpElem := range arrGrpElem {
			if bytes.Equal(grpElem.NodeId.Bytes(), nodeId.Bytes()) {
				return grpElem.Address
			}
		}
	}
	return ret
}

func (cnf *OsmConf) GetSelfWorkAddr() string {
	return cnf.GetWorkingAddrByNodeId(cnf.SelfNodeId)
}

//-----------------------others ---------------------------------

// compute f(x) x=hash(pk)
func (cnf *OsmConf) getPkHash(grpId string, smInx uint16) (common.Hash, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	pk, _ := cnf.GetPK(grpId, smInx)
	err := schcomm.CheckPK(pk)
	if err != nil {
		return common.Hash{}, err
	}
	h := sha256.Sum256(crypto.FromECDSAPub(pk))
	return h, nil
}

func (cnf *OsmConf) GetInxByNodeId(grpId string, id *discover.NodeID) (uint16, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	if id == nil {

		errStr := fmt.Sprintf("GetInxByNodeId id is null")
		log.Error("OsmConf.GetInxByNodeId", "err", errStr)
		return 0, errors.New(errStr)

	}

	//arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	//for _, value := range arrGrpElem {
	//	if *value.NodeId == *id {
	//		return value.Inx, nil
	//	}
	//}

	if index, exist := cnf.GrpIdNodeIdToIndx[grpId][id.String()]; exist {
		return index, nil
	}

	errStr := fmt.Sprintf("GetInxByNodeId not find index by nodeId, id:%v", id.SlimString())
	log.Error("OsmConf.GetInxByNodeId", "err", errStr)
	return 0, errors.New(errStr)

}

func (cnf *OsmConf) GetXValueByNodeId(grpId string, id *discover.NodeID, smpcer mpcprotocol.SchnorrMPCer) (*big.Int, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	if id == nil {
		log.SyslogInfo("GetXValueByNodeId id is null")

		errStr := fmt.Sprintf("GetXValueByNodeId id is null")
		log.SyslogErr("OsmConf.GetXValueByNodeId", "err", errStr)
		return nil, errors.New(errStr)

	}
	cnf.checkGrpId(grpId)
	index, _ := cnf.GetInxByNodeId(grpId, id)
	return cnf.GetXValueByIndex(grpId, index, smpcer)
}

func (cnf *OsmConf) GetNodeIdByIndex(grpId string, index uint16) (*discover.NodeID, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)

	//arrGrpElem := cnf.GrpInfoMap[grpId].ArrGrpElems
	//for _, value := range arrGrpElem {
	//	if value.Inx == index {
	//		return value.NodeId, nil
	//	}
	//}
	if nodeId, exist := cnf.GrpIdIndxToNodeId[grpId][index]; exist {
		return nodeId, nil
	}

	errStr := fmt.Sprintf("node id not found, grpId = %v, index = %v", grpId, index)
	log.SyslogErr("OsmConf.GetNodeIdByIndex", "err", errStr)
	return nil, errors.New(errStr)

}

func (cnf *OsmConf) GetXValueByIndex(grpId string, index uint16, smpcer mpcprotocol.SchnorrMPCer) (*big.Int, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)

	ge, err := cnf.getGrpItem(grpId, index)
	if err != nil {
		return big.NewInt(0), err
	} else {
		bigRet := big.NewInt(0).Mod(ge.XValue, smpcer.GetMod())
		//log.SyslogDebug("GetXValueByIndex bigRet", "ge.XValue", hexutil.Encode(bigRet.Bytes()))
		log.Trace("GetXValueByIndex bigRet", "ge.XValue", hexutil.Encode(bigRet.Bytes()))
		return bigRet, nil
	}
}

func (cnf *OsmConf) GetLeaderIndex(grpId string) (uint16, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)
	return cnf.GrpInfoMap[grpId].LeaderInx, nil
}

func (cnf *OsmConf) GetPeersByGrpId(grpId string) ([]mpcprotocol.PeerInfo, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()
	cnf.checkGrpId(grpId)
	peers := make([]mpcprotocol.PeerInfo, 0)
	grpElems, _ := cnf.getGrpElems(grpId)
	for _, grpElem := range *grpElems {
		peers = append(peers, mpcprotocol.PeerInfo{PeerID: *grpElem.NodeId, Seed: 0})
	}
	return peers, nil
}

func (cnf *OsmConf) GetAllPeersNodeIds() ([]discover.NodeID, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	nodeIdsMap := make(map[discover.NodeID]interface{})
	nodeIds := make([]discover.NodeID, 0)

	for _, grpInfo := range cnf.GrpInfoMap {

		grpElems, _ := cnf.getGrpElems(grpInfo.GrpId)
		for _, grpElem := range *grpElems {
			nodeIdsMap[*grpElem.NodeId] = nil
		}
	}

	for key, _ := range nodeIdsMap {
		nodeIds = append(nodeIds, key)
	}
	return nodeIds, nil
}

func (cnf *OsmConf) IsNodeIdInAllNodes(nodeId discover.NodeID) (bool, error) {

	bootId := cnf.GetBootNodeID()
	selfId, _ := cnf.GetSelfNodeId()
	if bootId == nil || selfId == nil {
		return true, nil
	}

	if bytes.Equal(bootId.Bytes(), selfId.Bytes()) {
		return true, nil
	}

	bInNodes := false

	if bytes.Equal(cnf.GetBootNodeID().Bytes(), nodeId.Bytes()) {
		bInNodes = true
	}

	defer cnf.wrLock.RUnlock()
	cnf.wrLock.RLock()

	if _, exist := cnf.mapAllGrpElems[nodeId.String()]; exist {
		bInNodes = true
	}
	return bInNodes, nil
}

func (cnf *OsmConf) GetPeersNodeIdsByGrpId(grpIdInput string) ([]discover.NodeID, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	nodeIdsMap := make(map[discover.NodeID]interface{})
	nodeIds := make([]discover.NodeID, 0)

	for grpId, grpInfo := range cnf.GrpInfoMap {
		if grpIdInput == grpId {
			grpElems, _ := cnf.getGrpElems(grpInfo.GrpId)
			for _, grpElem := range *grpElems {
				nodeIdsMap[*grpElem.NodeId] = nil
			}
		}
	}
	for key, _ := range nodeIdsMap {
		nodeIds = append(nodeIds, key)
	}
	return nodeIds, nil
}

func (cnf *OsmConf) IsLeader(grpId string) (bool, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	selfIndex, err := cnf.GetSelfInx(grpId)
	if err != nil {
		return false, err
	}
	leaderInx, err := cnf.GetLeaderIndex(grpId)
	if err != nil {
		return false, err
	}
	return selfIndex == leaderInx, nil

}

func (cnf *OsmConf) IsFromLeader(grpId string, fromId *discover.NodeID) (bool, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	cnf.checkGrpId(grpId)
	fromIndex, err := cnf.GetInxByNodeId(grpId, fromId)
	if err != nil {
		return false, err
	}
	leaderInx, err := cnf.GetLeaderIndex(grpId)
	if err != nil {
		return false, err
	}
	return fromIndex == leaderInx, nil

}

func (cnf *OsmConf) CheckOsmcnf() {
	if !cnf.checkOsmcnf() {
		panic("Check Osm Config fail!")
	}
}

func (cnf *OsmConf) checkOsmcnf_org() bool {
	for grpIdStr, gii := range cnf.GrpInfoMap {
		for _, grpCurve := range gii.ArrGrpCurves {
			curveType, err := strconv.Atoi(grpCurve.CurveType)
			if err != nil {
				log.SyslogErr("checkOsmcnf", "curveType error", err.Error())
				return false
			}
			gpk := grpCurve.Gpk
			gpkStr := hexutil.Encode(gpk)

			index, err := cnf.GetInxByNodeId(grpIdStr, cnf.SelfNodeId)
			if err != nil {
				log.SyslogErr("checkOsmcnf", "error", err.Error())
				return true
			}

			myPkShareByte, err := cnf.GetPKShareBytes(grpIdStr, gpkStr, index, uint16(curveType))
			if err != nil {
				log.SyslogErr("checkOsmcnf", "GetPKShareBytes error", err.Error())
				return false
			}

			myPkShareFromKs, err := cnf.getGpkShareFromKs(gpkStr, curveType)
			if err != nil {
				log.SyslogErr("checkOsmcnf", "getGpkShareFromKs error", err.Error())
				return false
			}

			if bytes.Compare(myPkShareByte[:], myPkShareFromKs) != 0 {
				log.SyslogErr("myGPkShare is not content with the one from keystore",
					"gpkShare from contract", hexutil.Encode(myPkShareByte),
					"gpkShare from keystore", hexutil.Encode(myPkShareFromKs))
				return false
			}
		}
	}

	return true
}

func (cnf *OsmConf) checkOsmcnf() bool {
	// faltIndex need get all groups (current and pre)
	// for users only belong current group, it has no gsk, so no need to check the gpk in ks inline with the one in group.json.
	return true
}

func (cnf *OsmConf) getGpkShareFromKs(gpkStr string, curveType int) ([]byte, error) {
	log.SyslogInfo("getGpkShareFromKs", "gpkStr", gpkStr, "curveType", curveType)
	smpcer := GetSmpcer(curveType)
	//pt, err := smpcer.StringToPt(gpkStr)
	//if err != nil {
	//	log.SyslogErr("getGpkShareFromKs", "StringToPt error", err.Error())
	//	return nil, err
	//}

	//address, err := smpcer.PtToAddress(pt)
	//if err != nil {
	//	log.SyslogErr("getGpkShareFromKs", "PtToAddress error", err.Error())
	//	return nil, err
	//}

	addr := common.HexToAddress(gpkStr)
	//gskShare, err := cnf.getGSkShareFromKs(gpkStr, curveType, address)
	gskShare, err := cnf.getGSkShareFromKs(gpkStr, curveType, addr)
	if err != nil {
		log.SyslogErr("getGpkShareFromKs", "getGSkShareFromKs error", err.Error())
		return nil, err
	}

	gpkShare, err := smpcer.SkG(gskShare)
	if err != nil {
		log.SyslogErr("getGpkShareFromKs", "SkG error", err.Error())
		return nil, err
	}

	gpkShareBytes, err := smpcer.MarshPt(gpkShare)
	if err != nil {
		log.SyslogErr("getGpkShareFromKs", "MarshPt error", err.Error())
		return nil, err
	}
	return gpkShareBytes, nil
}

func (cnf *OsmConf) getGSkShareFromKs(gpkStr string, curveType int, address common.Address) (*big.Int, error) {
	password, _ := cnf.GetGpkPwd(gpkStr)
	var key *keystore.Key
	var err error

	ks := cnf.AccMng.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
	//key, _, err = GetPrivateShare(ks, address, true, nil, password)
	key, _, err = GetPrivateShare(ks, address, true, cnf.KmsInfo(), password)
	if err != nil {
		return nil, err
	}

	return key.PrivateKey.D, nil
}

func (cnf *OsmConf) SetBootNodeID(nodeId *discover.NodeID) {
	cnf.bootNodeID = nodeId
}

func (cnf *OsmConf) GetBootNodeID() *discover.NodeID {
	return cnf.bootNodeID
}

//////////////////////////////////util/////////////////////////////

// intersection
func intersect(slice1, slice2 []uint16) []uint16 {
	m := make(map[uint16]int)
	ret := make([]uint16, 0)
	for _, v := range slice1 {
		m[v]++
	}

	for _, v := range slice2 {
		times, _ := m[v]
		if times == 1 {
			ret = append(ret, v)
		}
	}
	return ret
}

func Difference(slice1, slice2 []uint16) []uint16 {
	m := make(map[uint16]int)
	ret := make([]uint16, 0)
	inter := intersect(slice1, slice2)
	for _, v := range inter {
		m[v]++
	}

	for _, value := range slice1 {
		times, _ := m[value]
		if times == 0 {
			ret = append(ret, value)
		}
	}
	return ret
}

func pkToAddr(PkBytes []byte) (common.Address, error) {
	if len(PkBytes) != 65 {
		return common.Address{}, errors.New("invalid pk address in osmconf.go")
	}
	pk := crypto.ToECDSAPub(PkBytes[:])
	address := crypto.PubkeyToAddress(*pk)
	return address, nil
}

func GetGrpId(mpcResult mpcprotocol.MpcResultInterface) ([]byte, string, error) {
	if mpcResult == nil {
		log.SyslogErr("GetGrpId error", "error", "mpcresult is nil")
		return []byte{}, "", errors.New("in function GetGrpId mpcresult is nil")
	}
	grpId, err := mpcResult.GetByteValue("MpcGrpId")
	if err != nil {
		log.SyslogErr("GetGrpId error", "error", err.Error())
		return []byte{}, "", err
	}

	grpIdString := hexutil.Encode(grpId)
	return grpId, grpIdString, nil
}

func GetGrpGpk(mpcResult mpcprotocol.MpcResultInterface) ([]byte, string, error) {
	if mpcResult == nil {
		log.SyslogErr("GetGrpId error", "error", "mpcresult is nil")
		return []byte{}, "", errors.New("in function GetGrpId mpcresult is nil")
	}
	gpkId, err := mpcResult.GetByteValue(mpcprotocol.MpcGpkBytes)
	if err != nil {
		log.SyslogErr("GetGrp error", "error", err.Error())
		return []byte{}, "", err
	}

	gpkIdString := hexutil.Encode(gpkId)
	return gpkId, gpkIdString, nil
}

func BuildDataByIndexes(indexes *[]big.Int) (*big.Int, error) {

	if indexes == nil {
		log.SyslogErr("BuildDataByIndexes indexes is null")
		return schcomm.BigZero, errors.New("invalid point")
	}

	ret := schcomm.BigZero
	bigTm := big.NewInt(0)
	bigTm.Add(schcomm.BigOne, schcomm.BigOne)

	for _, indexBig := range *indexes {
		bigTm1 := big.NewInt(0)
		bigTm1.Exp(bigTm, &indexBig, nil)
		ret = big.NewInt(0).Add(ret, bigTm1)
	}
	return ret, nil
}

func BuildStrByIndexes(indexes *[]big.Int) (string, error) {

	if indexes == nil {
		log.SyslogErr("BuildStringByIndexes indexes is null")
		return "", errors.New("invalid point")
	}

	var buf bytes.Buffer

	for _, indexBig := range *indexes {
		buf.WriteString(hexutil.Encode(indexBig.Bytes()))
	}
	return buf.String(), nil
}

func InterSecByIndexes(indexes *[]big.Int) (*big.Int, error) {
	if indexes == nil {
		log.SyslogErr("BuildDataByIndexes indexes is null")
		return schcomm.BigZero, errors.New("invalid point")
	}
	if len(*indexes) == 0 {
		return nil, errors.New("no indexes needed to be intersected")
	}
	var ret *big.Int
	ret = big.NewInt(0).SetBytes((*indexes)[0].Bytes()) //should not change the original data
	//ret = &(*indexes)[0]

	for i := 1; i < len(*indexes); i++ {
		ret.And(ret, &(*indexes)[i])
	}
	return ret, nil
}

func IsHaming(sendCol *big.Int, smIndex uint16) (bool, error) {
	if sendCol == nil {
		return false, nil
	}

	b := sendCol.Bit(int(smIndex))
	return b == uint(1), nil
}

func Hams(sendCol *big.Int, totalNum uint16) (uint16, error) {
	var ret uint16
	if sendCol == nil {
		return 0, nil
	}
	for i := uint16(0); i < totalNum; i++ {
		if ham, _ := IsHaming(sendCol, i); ham {
			ret++
		}
	}
	return ret, nil
}

func PathExists(path string) (bool, error) {

	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

//////////////// test only begin///////////////

func (cnf *OsmConf) GetPrivateShareMock(curveType uint8) (big.Int, error) {
	defer cnf.wrLock.RUnlock()

	cnf.wrLock.RLock()

	switch int(curveType) {
	case mpcprotocol.SK256Curve:
		// gpk: 0x04ee8797b2d53915708fb24cee7dbdddfa43eb2cbfa19cd427cdfd02d2169bb028e5dfa3514a92fa2eb4da42085bbc7807c1acb08f132c13b2951759d4281ece8b
		nodeId, _ := cnf.GetSelfNodeId()
		if hexutil.Encode((*nodeId)[:]) == "0xed214e8ce499d92a2085e7e6041b4f081c7d29d8770057fc705a131d2918fcdb737e23980bdd11fa86f5d824ea1f8a35333ac6f99246464dd4d19adac9da21d1" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x09f49a365fea55e3d8241510d97a4e1e68582db38719d88dcf497a15731cf151"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0xe6d15450a252e2209574a98585785a79c160746fa282a8ab9d4658c381093928eda1f03e70606dd4eee6402389c619ac9f725c63e5b80b947730d31152ce6612" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0xd7a1fd5acd23d2bd8b0ec0526686623c9b1d9d6d083b52f6dbc730b60db99cf8"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0xf938ff60f1e8ebea4c229d894c98418e90c149814ed7909c3dd47cb015cd1f15d71722121a0cc646a0576e29372bfbd6037fe2c5b6ed68214da50318eebb13e1" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x5f5df44ef5540f264f1d15172ab19218ce90ab23821f38715b3d040fcc44fbca"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0x3d7346cf5ac1dfa9beace3f93b215acc8cf4bb2b1653f50649e803a60e91c7dc41d9f491afbc0199633caaa298233139d53ac64556c51ea654d52eca70b5e9c7" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x5118cb40b295744ccdbf0e05f31f3876e448f36d58288d2a18e49e99c5aa1bff"))), nil
		}
	case mpcprotocol.BN256Curve:
		// gpk: 0x2ab2e3655ebd58b188f9ed3ba466e3ae39f4f6e9bcbe80e355be8f1ccd222f97175ebb6b000cb43a3aa6e69dd05d1710719559b17983a0067420de99f3c3cd9f
		nodeId, _ := cnf.GetSelfNodeId()
		if hexutil.Encode((*nodeId)[:]) == "0xed214e8ce499d92a2085e7e6041b4f081c7d29d8770057fc705a131d2918fcdb737e23980bdd11fa86f5d824ea1f8a35333ac6f99246464dd4d19adac9da21d1" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x5a7923a1eca58361ba627cb39e83b6e26fc514090d429df4f296b3c9125c32d6"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0xe6d15450a252e2209574a98585785a79c160746fa282a8ab9d4658c381093928eda1f03e70606dd4eee6402389c619ac9f725c63e5b80b947730d31152ce6612" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x70f5fdceb9d3d7442628479d8cbd9da3abe28a08a88f6477084740bd704630a4"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0xf938ff60f1e8ebea4c229d894c98418e90c149814ed7909c3dd47cb015cd1f15d71722121a0cc646a0576e29372bfbd6037fe2c5b6ed68214da50318eebb13e1" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x48852ab57a33421453103162023e03d500d7c48b3a28a5704ae4ba87a311f471"))), nil
		}

		if hexutil.Encode((*nodeId)[:]) == "0x3d7346cf5ac1dfa9beace3f93b215acc8cf4bb2b1653f50649e803a60e91c7dc41d9f491afbc0199633caaa298233139d53ac64556c51ea654d52eca70b5e9c7" {
			return *big.NewInt(0).SetBytes(hexutil.MustDecode(string("0x560d4b7454827624a47da45970b071f0a7baf0975ac88345855baa3200820f48"))), nil
		}
	default:
		return big.Int{}, nil
	}
	return big.Int{}, nil
}

func makeAccountManagerMock(keydir string) (*accounts.Manager, string, error) {
	scryptN := keystore.StandardScryptN
	scryptP := keystore.StandardScryptP

	backends := []accounts.Backend{
		keystore.NewKeyStore(keydir, scryptN, scryptP),
	}

	return accounts.NewManager(backends...), "", nil
}

//////////////// test only end///////////////
